﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SpiceNet.Circuits;
using SpiceNet.Simulations;
using SpiceNet.Models.BSIM2p;
using SpiceNet.Parameters;
using SpiceNet.Diagnostics;

namespace SpiceNet.Models
{
    /// <summary>
    /// A BSIM2 transistor model
    /// </summary>
    public class BSIM2Model : Model
    {
        /// <summary>
        /// Get parameters
        /// </summary>
        public override Dictionary<string, IP> ParamTable => _pTable;

        /// <summary>
        /// Internally calculated variables
        /// </summary>
        public Dictionary<Tuple<double, double>, SizeDependParam> Params = new Dictionary<Tuple<double, double>, SizeDependParam>();

        #region Parameters
        private enum _c
        {
            /* model parameters */
            BSIM2_MOD_VFB0 = 101,
            BSIM2_MOD_VFBL = 102,
            BSIM2_MOD_VFBW = 103,
            BSIM2_MOD_PHI0 = 104,
            BSIM2_MOD_PHIL = 105,
            BSIM2_MOD_PHIW = 106,
            BSIM2_MOD_K10 = 107,
            BSIM2_MOD_K1L = 108,
            BSIM2_MOD_K1W = 109,
            BSIM2_MOD_K20 = 110,
            BSIM2_MOD_K2L = 111,
            BSIM2_MOD_K2W = 112,
            BSIM2_MOD_ETA00 = 113,
            BSIM2_MOD_ETA0L = 114,
            BSIM2_MOD_ETA0W = 115,
            BSIM2_MOD_ETAB0 = 116,
            BSIM2_MOD_ETABL = 117,
            BSIM2_MOD_ETABW = 118,
            BSIM2_MOD_DELTAL = 119,
            BSIM2_MOD_DELTAW = 120,
            BSIM2_MOD_MOB00 = 121,
            BSIM2_MOD_MOB0B0 = 122,
            BSIM2_MOD_MOB0BL = 123,
            BSIM2_MOD_MOB0BW = 124,
            BSIM2_MOD_MOBS00 = 125,
            BSIM2_MOD_MOBS0L = 126,
            BSIM2_MOD_MOBS0W = 127,
            BSIM2_MOD_MOBSB0 = 128,
            BSIM2_MOD_MOBSBL = 129,
            BSIM2_MOD_MOBSBW = 130,
            BSIM2_MOD_MOB200 = 131,
            BSIM2_MOD_MOB20L = 132,
            BSIM2_MOD_MOB20W = 133,
            BSIM2_MOD_MOB2B0 = 134,
            BSIM2_MOD_MOB2BL = 135,
            BSIM2_MOD_MOB2BW = 136,
            BSIM2_MOD_MOB2G0 = 137,
            BSIM2_MOD_MOB2GL = 138,
            BSIM2_MOD_MOB2GW = 139,
            BSIM2_MOD_MOB300 = 140,
            BSIM2_MOD_MOB30L = 141,
            BSIM2_MOD_MOB30W = 142,
            BSIM2_MOD_MOB3B0 = 143,
            BSIM2_MOD_MOB3BL = 144,
            BSIM2_MOD_MOB3BW = 145,
            BSIM2_MOD_MOB3G0 = 146,
            BSIM2_MOD_MOB3GL = 147,
            BSIM2_MOD_MOB3GW = 148,
            BSIM2_MOD_MOB400 = 149,
            BSIM2_MOD_MOB40L = 150,
            BSIM2_MOD_MOB40W = 151,
            BSIM2_MOD_MOB4B0 = 152,
            BSIM2_MOD_MOB4BL = 153,
            BSIM2_MOD_MOB4BW = 154,
            BSIM2_MOD_MOB4G0 = 155,
            BSIM2_MOD_MOB4GL = 156,
            BSIM2_MOD_MOB4GW = 157,
            BSIM2_MOD_UA00 = 158,
            BSIM2_MOD_UA0L = 159,
            BSIM2_MOD_UA0W = 160,
            BSIM2_MOD_UAB0 = 161,
            BSIM2_MOD_UABL = 162,
            BSIM2_MOD_UABW = 163,
            BSIM2_MOD_UB00 = 164,
            BSIM2_MOD_UB0L = 165,
            BSIM2_MOD_UB0W = 166,
            BSIM2_MOD_UBB0 = 167,
            BSIM2_MOD_UBBL = 168,
            BSIM2_MOD_UBBW = 169,
            BSIM2_MOD_U100 = 170,
            BSIM2_MOD_U10L = 171,
            BSIM2_MOD_U10W = 172,
            BSIM2_MOD_U1B0 = 173,
            BSIM2_MOD_U1BL = 174,
            BSIM2_MOD_U1BW = 175,
            BSIM2_MOD_U1D0 = 176,
            BSIM2_MOD_U1DL = 177,
            BSIM2_MOD_U1DW = 178,
            BSIM2_MOD_N00 = 179,
            BSIM2_MOD_N0L = 180,
            BSIM2_MOD_N0W = 181,
            BSIM2_MOD_NB0 = 182,
            BSIM2_MOD_NBL = 183,
            BSIM2_MOD_NBW = 184,
            BSIM2_MOD_ND0 = 185,
            BSIM2_MOD_NDL = 186,
            BSIM2_MOD_NDW = 187,
            BSIM2_MOD_VOF00 = 188,
            BSIM2_MOD_VOF0L = 189,
            BSIM2_MOD_VOF0W = 190,
            BSIM2_MOD_VOFB0 = 191,
            BSIM2_MOD_VOFBL = 192,
            BSIM2_MOD_VOFBW = 193,
            BSIM2_MOD_VOFD0 = 194,
            BSIM2_MOD_VOFDL = 195,
            BSIM2_MOD_VOFDW = 196,
            BSIM2_MOD_AI00 = 197,
            BSIM2_MOD_AI0L = 198,
            BSIM2_MOD_AI0W = 199,
            BSIM2_MOD_AIB0 = 200,
            BSIM2_MOD_AIBL = 201,
            BSIM2_MOD_AIBW = 202,
            BSIM2_MOD_BI00 = 203,
            BSIM2_MOD_BI0L = 204,
            BSIM2_MOD_BI0W = 205,
            BSIM2_MOD_BIB0 = 206,
            BSIM2_MOD_BIBL = 207,
            BSIM2_MOD_BIBW = 208,
            BSIM2_MOD_VGHIGH0 = 209,
            BSIM2_MOD_VGHIGHL = 210,
            BSIM2_MOD_VGHIGHW = 211,
            BSIM2_MOD_VGLOW0 = 212,
            BSIM2_MOD_VGLOWL = 213,
            BSIM2_MOD_VGLOWW = 214,
            BSIM2_MOD_TOX = 215,
            BSIM2_MOD_TEMP = 216,
            BSIM2_MOD_VDD = 217,
            BSIM2_MOD_VGG = 218,
            BSIM2_MOD_VBB = 219,
            BSIM2_MOD_CGSO = 220,
            BSIM2_MOD_CGDO = 221,
            BSIM2_MOD_CGBO = 222,
            BSIM2_MOD_XPART = 223,
            BSIM2_MOD_RSH = 224,
            BSIM2_MOD_JS = 225,
            BSIM2_MOD_PB = 226,
            BSIM2_MOD_MJ = 227,
            BSIM2_MOD_PBSW = 228,
            BSIM2_MOD_MJSW = 229,
            BSIM2_MOD_CJ = 230,
            BSIM2_MOD_CJSW = 231,
            BSIM2_MOD_DEFWIDTH = 232,
            BSIM2_MOD_DELLENGTH = 233,
            BSIM2_MOD_NMOS = 234,
            BSIM2_MOD_PMOS = 235
        }
        private static Dictionary<string, IP> _pTable = new Dictionary<string, IP>
        {
            { "vfb", new IP(IF.IOP, (int)_c.BSIM2_MOD_VFB0, T.REAL, "Flat band voltage") },
            { "lvfb", new IP(IF.IOP, (int)_c.BSIM2_MOD_VFBL, T.REAL, "Length dependence of vfb") },
            { "wvfb", new IP(IF.IOP, (int)_c.BSIM2_MOD_VFBW, T.REAL, "Width dependence of vfb") },
            { "phi", new IP(IF.IOP, (int)_c.BSIM2_MOD_PHI0, T.REAL, "Strong inversion surface potential ") },
            { "lphi", new IP(IF.IOP, (int)_c.BSIM2_MOD_PHIL, T.REAL, "Length dependence of phi") },
            { "wphi", new IP(IF.IOP, (int)_c.BSIM2_MOD_PHIW, T.REAL, "Width dependence of phi") },
            { "k1", new IP(IF.IOP, (int)_c.BSIM2_MOD_K10, T.REAL, "Bulk effect coefficient 1") },
            { "lk1", new IP(IF.IOP, (int)_c.BSIM2_MOD_K1L, T.REAL, "Length dependence of k1") },
            { "wk1", new IP(IF.IOP, (int)_c.BSIM2_MOD_K1W, T.REAL, "Width dependence of k1") },
            { "k2", new IP(IF.IOP, (int)_c.BSIM2_MOD_K20, T.REAL, "Bulk effect coefficient 2") },
            { "lk2", new IP(IF.IOP, (int)_c.BSIM2_MOD_K2L, T.REAL, "Length dependence of k2") },
            { "wk2", new IP(IF.IOP, (int)_c.BSIM2_MOD_K2W, T.REAL, "Width dependence of k2") },
            { "eta0", new IP(IF.IOP, (int)_c.BSIM2_MOD_ETA00, T.REAL, "VDS dependence of threshold voltage at VDD=0") },
            { "leta0", new IP(IF.IOP, (int)_c.BSIM2_MOD_ETA0L, T.REAL, "Length dependence of eta0") },
            { "weta0", new IP(IF.IOP, (int)_c.BSIM2_MOD_ETA0W, T.REAL, "Width dependence of eta0") },
            { "etab", new IP(IF.IOP, (int)_c.BSIM2_MOD_ETAB0, T.REAL, "VBS dependence of eta") },
            { "letab", new IP(IF.IOP, (int)_c.BSIM2_MOD_ETABL, T.REAL, "Length dependence of etab") },
            { "wetab", new IP(IF.IOP, (int)_c.BSIM2_MOD_ETABW, T.REAL, "Width dependence of etab") },
            { "dl", new IP(IF.IOP, (int)_c.BSIM2_MOD_DELTAL, T.REAL, "Channel length reduction in um") },
            { "dw", new IP(IF.IOP, (int)_c.BSIM2_MOD_DELTAW, T.REAL, "Channel width reduction in um") },
            { "mu0", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB00, T.REAL, "Low-field mobility, at VDS=0 VGS=VTH") },
            { "mu0b", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB0B0, T.REAL, "VBS dependence of low-field mobility") },
            { "lmu0b", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB0BL, T.REAL, "Length dependence of mu0b") },
            { "wmu0b", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB0BW, T.REAL, "Width dependence of mu0b") },
            { "mus0", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOBS00, T.REAL, "Mobility at VDS=VDD VGS=VTH") },
            { "lmus0", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOBS0L, T.REAL, "Length dependence of mus0") },
            { "wmus0", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOBS0W, T.REAL, "Width dependence of mus") },
            { "musb", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOBSB0, T.REAL, "VBS dependence of mus") },
            { "lmusb", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOBSBL, T.REAL, "Length dependence of musb") },
            { "wmusb", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOBSBW, T.REAL, "Width dependence of musb") },
            { "mu20", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB200, T.REAL, "VDS dependence of mu in tanh term") },
            { "lmu20", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB20L, T.REAL, "Length dependence of mu20") },
            { "wmu20", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB20W, T.REAL, "Width dependence of mu20") },
            { "mu2b", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB2B0, T.REAL, "VBS dependence of mu2") },
            { "lmu2b", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB2BL, T.REAL, "Length dependence of mu2b") },
            { "wmu2b", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB2BW, T.REAL, "Width dependence of mu2b") },
            { "mu2g", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB2G0, T.REAL, "VGS dependence of mu2") },
            { "lmu2g", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB2GL, T.REAL, "Length dependence of mu2g") },
            { "wmu2g", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB2GW, T.REAL, "Width dependence of mu2g") },
            { "mu30", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB300, T.REAL, "VDS dependence of mu in linear term") },
            { "lmu30", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB30L, T.REAL, "Length dependence of mu30") },
            { "wmu30", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB30W, T.REAL, "Width dependence of mu30") },
            { "mu3b", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB3B0, T.REAL, "VBS dependence of mu3") },
            { "lmu3b", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB3BL, T.REAL, "Length dependence of mu3b") },
            { "wmu3b", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB3BW, T.REAL, "Width dependence of mu3b") },
            { "mu3g", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB3G0, T.REAL, "VGS dependence of mu3") },
            { "lmu3g", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB3GL, T.REAL, "Length dependence of mu3g") },
            { "wmu3g", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB3GW, T.REAL, "Width dependence of mu3g") },
            { "mu40", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB400, T.REAL, "VDS dependence of mu in linear term") },
            { "lmu40", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB40L, T.REAL, "Length dependence of mu40") },
            { "wmu40", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB40W, T.REAL, "Width dependence of mu40") },
            { "mu4b", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB4B0, T.REAL, "VBS dependence of mu4") },
            { "lmu4b", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB4BL, T.REAL, "Length dependence of mu4b") },
            { "wmu4b", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB4BW, T.REAL, "Width dependence of mu4b") },
            { "mu4g", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB4G0, T.REAL, "VGS dependence of mu4") },
            { "lmu4g", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB4GL, T.REAL, "Length dependence of mu4g") },
            { "wmu4g", new IP(IF.IOP, (int)_c.BSIM2_MOD_MOB4GW, T.REAL, "Width dependence of mu4g") },
            { "ua0", new IP(IF.IOP, (int)_c.BSIM2_MOD_UA00, T.REAL, "Linear VGS dependence of mobility") },
            { "lua0", new IP(IF.IOP, (int)_c.BSIM2_MOD_UA0L, T.REAL, "Length dependence of ua0") },
            { "wua0", new IP(IF.IOP, (int)_c.BSIM2_MOD_UA0W, T.REAL, "Width dependence of ua0") },
            { "uab", new IP(IF.IOP, (int)_c.BSIM2_MOD_UAB0, T.REAL, "VBS dependence of ua") },
            { "luab", new IP(IF.IOP, (int)_c.BSIM2_MOD_UABL, T.REAL, "Length dependence of uab") },
            { "wuab", new IP(IF.IOP, (int)_c.BSIM2_MOD_UABW, T.REAL, "Width dependence of uab") },
            { "ub0", new IP(IF.IOP, (int)_c.BSIM2_MOD_UB00, T.REAL, "Quadratic VGS dependence of mobility") },
            { "lub0", new IP(IF.IOP, (int)_c.BSIM2_MOD_UB0L, T.REAL, "Length dependence of ub0") },
            { "wub0", new IP(IF.IOP, (int)_c.BSIM2_MOD_UB0W, T.REAL, "Width dependence of ub0") },
            { "ubb", new IP(IF.IOP, (int)_c.BSIM2_MOD_UBB0, T.REAL, "VBS dependence of ub") },
            { "lubb", new IP(IF.IOP, (int)_c.BSIM2_MOD_UBBL, T.REAL, "Length dependence of ubb") },
            { "wubb", new IP(IF.IOP, (int)_c.BSIM2_MOD_UBBW, T.REAL, "Width dependence of ubb") },
            { "u10", new IP(IF.IOP, (int)_c.BSIM2_MOD_U100, T.REAL, "VDS depence of mobility") },
            { "lu10", new IP(IF.IOP, (int)_c.BSIM2_MOD_U10L, T.REAL, "Length dependence of u10") },
            { "wu10", new IP(IF.IOP, (int)_c.BSIM2_MOD_U10W, T.REAL, "Width dependence of u10") },
            { "u1b", new IP(IF.IOP, (int)_c.BSIM2_MOD_U1B0, T.REAL, "VBS depence of u1") },
            { "lu1b", new IP(IF.IOP, (int)_c.BSIM2_MOD_U1BL, T.REAL, "Length depence of u1b") },
            { "wu1b", new IP(IF.IOP, (int)_c.BSIM2_MOD_U1BW, T.REAL, "Width depence of u1b") },
            { "u1d", new IP(IF.IOP, (int)_c.BSIM2_MOD_U1D0, T.REAL, "VDS depence of u1") },
            { "lu1d", new IP(IF.IOP, (int)_c.BSIM2_MOD_U1DL, T.REAL, "Length depence of u1d") },
            { "wu1d", new IP(IF.IOP, (int)_c.BSIM2_MOD_U1DW, T.REAL, "Width depence of u1d") },
            { "n0", new IP(IF.IOP, (int)_c.BSIM2_MOD_N00, T.REAL, "Subthreshold slope at VDS=0 VBS=0") },
            { "ln0", new IP(IF.IOP, (int)_c.BSIM2_MOD_N0L, T.REAL, "Length dependence of n0") },
            { "wn0", new IP(IF.IOP, (int)_c.BSIM2_MOD_N0W, T.REAL, "Width dependence of n0") },
            { "nb", new IP(IF.IOP, (int)_c.BSIM2_MOD_NB0, T.REAL, "VBS dependence of n") },
            { "lnb", new IP(IF.IOP, (int)_c.BSIM2_MOD_NBL, T.REAL, "Length dependence of nb") },
            { "wnb", new IP(IF.IOP, (int)_c.BSIM2_MOD_NBW, T.REAL, "Width dependence of nb") },
            { "nd", new IP(IF.IOP, (int)_c.BSIM2_MOD_ND0, T.REAL, "VDS dependence of n") },
            { "lnd", new IP(IF.IOP, (int)_c.BSIM2_MOD_NDL, T.REAL, "Length dependence of nd") },
            { "wnd", new IP(IF.IOP, (int)_c.BSIM2_MOD_NDW, T.REAL, "Width dependence of nd") },
            { "vof0", new IP(IF.IOP, (int)_c.BSIM2_MOD_VOF00, T.REAL, "Threshold voltage offset AT VDS=0 VBS=0") },
            { "lvof0", new IP(IF.IOP, (int)_c.BSIM2_MOD_VOF0L, T.REAL, "Length dependence of vof0") },
            { "wvof0", new IP(IF.IOP, (int)_c.BSIM2_MOD_VOF0W, T.REAL, "Width dependence of vof0") },
            { "vofb", new IP(IF.IOP, (int)_c.BSIM2_MOD_VOFB0, T.REAL, "VBS dependence of vof") },
            { "lvofb", new IP(IF.IOP, (int)_c.BSIM2_MOD_VOFBL, T.REAL, "Length dependence of vofb") },
            { "wvofb", new IP(IF.IOP, (int)_c.BSIM2_MOD_VOFBW, T.REAL, "Width dependence of vofb") },
            { "vofd", new IP(IF.IOP, (int)_c.BSIM2_MOD_VOFD0, T.REAL, "VDS dependence of vof") },
            { "lvofd", new IP(IF.IOP, (int)_c.BSIM2_MOD_VOFDL, T.REAL, "Length dependence of vofd") },
            { "wvofd", new IP(IF.IOP, (int)_c.BSIM2_MOD_VOFDW, T.REAL, "Width dependence of vofd") },
            { "ai0", new IP(IF.IOP, (int)_c.BSIM2_MOD_AI00, T.REAL, "Pre-factor of hot-electron effect.") },
            { "lai0", new IP(IF.IOP, (int)_c.BSIM2_MOD_AI0L, T.REAL, "Length dependence of ai0") },
            { "wai0", new IP(IF.IOP, (int)_c.BSIM2_MOD_AI0W, T.REAL, "Width dependence of ai0") },
            { "aib", new IP(IF.IOP, (int)_c.BSIM2_MOD_AIB0, T.REAL, "VBS dependence of ai") },
            { "laib", new IP(IF.IOP, (int)_c.BSIM2_MOD_AIBL, T.REAL, "Length dependence of aib") },
            { "waib", new IP(IF.IOP, (int)_c.BSIM2_MOD_AIBW, T.REAL, "Width dependence of aib") },
            { "bi0", new IP(IF.IOP, (int)_c.BSIM2_MOD_BI00, T.REAL, "Exponential factor of hot-electron effect.") },
            { "lbi0", new IP(IF.IOP, (int)_c.BSIM2_MOD_BI0L, T.REAL, "Length dependence of bi0") },
            { "wbi0", new IP(IF.IOP, (int)_c.BSIM2_MOD_BI0W, T.REAL, "Width dependence of bi0") },
            { "bib", new IP(IF.IOP, (int)_c.BSIM2_MOD_BIB0, T.REAL, "VBS dependence of bi") },
            { "lbib", new IP(IF.IOP, (int)_c.BSIM2_MOD_BIBL, T.REAL, "Length dependence of bib") },
            { "wbib", new IP(IF.IOP, (int)_c.BSIM2_MOD_BIBW, T.REAL, "Width dependence of bib") },
            { "vghigh", new IP(IF.IOP, (int)_c.BSIM2_MOD_VGHIGH0, T.REAL, "Upper bound of the cubic spline function.") },
            { "lvghigh", new IP(IF.IOP, (int)_c.BSIM2_MOD_VGHIGHL, T.REAL, "Length dependence of vghigh") },
            { "wvghigh", new IP(IF.IOP, (int)_c.BSIM2_MOD_VGHIGHW, T.REAL, "Width dependence of vghigh") },
            { "vglow", new IP(IF.IOP, (int)_c.BSIM2_MOD_VGLOW0, T.REAL, "Lower bound of the cubic spline function.") },
            { "lvglow", new IP(IF.IOP, (int)_c.BSIM2_MOD_VGLOWL, T.REAL, "Length dependence of vglow") },
            { "wvglow", new IP(IF.IOP, (int)_c.BSIM2_MOD_VGLOWW, T.REAL, "Width dependence of vglow") },
            { "tox", new IP(IF.IOP, (int)_c.BSIM2_MOD_TOX, T.REAL, "Gate oxide thickness in um") },
            { "temp", new IP(IF.IOP, (int)_c.BSIM2_MOD_TEMP, T.REAL, "Temperature in degree Celcius") },
            { "vdd", new IP(IF.IOP, (int)_c.BSIM2_MOD_VDD, T.REAL, "Maximum Vds ") },
            { "vgg", new IP(IF.IOP, (int)_c.BSIM2_MOD_VGG, T.REAL, "Maximum Vgs ") },
            { "vbb", new IP(IF.IOP, (int)_c.BSIM2_MOD_VBB, T.REAL, "Maximum Vbs ") },
            { "cgso", new IP(IF.IOPA, (int)_c.BSIM2_MOD_CGSO, T.REAL, "Gate source overlap capacitance per unit channel width(m)") },
            { "cgdo", new IP(IF.IOPA, (int)_c.BSIM2_MOD_CGDO, T.REAL, "Gate drain overlap capacitance per unit channel width(m)") },
            { "cgbo", new IP(IF.IOPA, (int)_c.BSIM2_MOD_CGBO, T.REAL, "Gate bulk overlap capacitance per unit channel length(m)") },
            { "xpart", new IP(IF.IOP, (int)_c.BSIM2_MOD_XPART, T.REAL, "Flag for channel charge partitioning") },
            { "rsh", new IP(IF.IOP, (int)_c.BSIM2_MOD_RSH, T.REAL, "Source drain diffusion sheet resistance in ohm per square") },
            { "js", new IP(IF.IOP, (int)_c.BSIM2_MOD_JS, T.REAL, "Source drain junction saturation current per unit area") },
            { "pb", new IP(IF.IOP, (int)_c.BSIM2_MOD_PB, T.REAL, "Source drain junction built in potential") },
            { "mj", new IP(IF.IOPA, (int)_c.BSIM2_MOD_MJ, T.REAL, "Source drain bottom junction capacitance grading coefficient") },
            { "pbsw", new IP(IF.IOPA, (int)_c.BSIM2_MOD_PBSW, T.REAL, "Source drain side junction capacitance built in potential") },
            { "mjsw", new IP(IF.IOPA, (int)_c.BSIM2_MOD_MJSW, T.REAL, "Source drain side junction capacitance grading coefficient") },
            { "cj", new IP(IF.IOPA, (int)_c.BSIM2_MOD_CJ, T.REAL, "Source drain bottom junction capacitance per unit area") },
            { "cjsw", new IP(IF.IOPA, (int)_c.BSIM2_MOD_CJSW, T.REAL, "Source drain side junction capacitance per unit area") },
            { "wdf", new IP(IF.IOP, (int)_c.BSIM2_MOD_DEFWIDTH, T.REAL, "Default width of source drain diffusion in um") },
            { "dell", new IP(IF.IOP, (int)_c.BSIM2_MOD_DELLENGTH, T.REAL, "Length reduction of source drain diffusion") },
            { "nmos", new IP(IF.IP, (int)_c.BSIM2_MOD_NMOS, T.FLAG, "Flag to indicate NMOS") },
            { "pmos", new IP(IF.IP, (int)_c.BSIM2_MOD_PMOS, T.FLAG, "Flag to indicate PMOS") }
        };

        public Parameter<double> B2vfb0 { get; } = new Parameter<double>(-1.0);
        public Parameter<double> B2vfbL { get; } = new Parameter<double>();
        public Parameter<double> B2vfbW { get; } = new Parameter<double>();
        public Parameter<double> B2phi0 { get; } = new Parameter<double>(0.75);
        public Parameter<double> B2phiL { get; } = new Parameter<double>();
        public Parameter<double> B2phiW { get; } = new Parameter<double>();
        public Parameter<double> B2k10 { get; } = new Parameter<double>(0.8);
        public Parameter<double> B2k1L { get; } = new Parameter<double>();
        public Parameter<double> B2k1W { get; } = new Parameter<double>();
        public Parameter<double> B2k20 { get; } = new Parameter<double>();
        public Parameter<double> B2k2L { get; } = new Parameter<double>();
        public Parameter<double> B2k2W { get; } = new Parameter<double>();
        public Parameter<double> B2eta00 { get; } = new Parameter<double>();
        public Parameter<double> B2eta0L { get; } = new Parameter<double>();
        public Parameter<double> B2eta0W { get; } = new Parameter<double>();
        public Parameter<double> B2etaB0 { get; } = new Parameter<double>();
        public Parameter<double> B2etaBL { get; } = new Parameter<double>();
        public Parameter<double> B2etaBW { get; } = new Parameter<double>();
        public Parameter<double> B2deltaL { get; } = new Parameter<double>();
        public Parameter<double> B2deltaW { get; } = new Parameter<double>();
        public Parameter<double> B2mob00 { get; } = new Parameter<double>(400.0);
        public Parameter<double> B2mob0B0 { get; } = new Parameter<double>();
        public Parameter<double> B2mob0BL { get; } = new Parameter<double>();
        public Parameter<double> B2mob0BW { get; } = new Parameter<double>();
        public Parameter<double> B2mobs00 { get; } = new Parameter<double>(500.0);
        public Parameter<double> B2mobs0L { get; } = new Parameter<double>();
        public Parameter<double> B2mobs0W { get; } = new Parameter<double>();
        public Parameter<double> B2mobsB0 { get; } = new Parameter<double>();
        public Parameter<double> B2mobsBL { get; } = new Parameter<double>();
        public Parameter<double> B2mobsBW { get; } = new Parameter<double>();
        public Parameter<double> B2mob200 { get; } = new Parameter<double>(1.5);
        public Parameter<double> B2mob20L { get; } = new Parameter<double>();
        public Parameter<double> B2mob20W { get; } = new Parameter<double>();
        public Parameter<double> B2mob2B0 { get; } = new Parameter<double>();
        public Parameter<double> B2mob2BL { get; } = new Parameter<double>();
        public Parameter<double> B2mob2BW { get; } = new Parameter<double>();
        public Parameter<double> B2mob2G0 { get; } = new Parameter<double>();
        public Parameter<double> B2mob2GL { get; } = new Parameter<double>();
        public Parameter<double> B2mob2GW { get; } = new Parameter<double>();
        public Parameter<double> B2mob300 { get; } = new Parameter<double>(10);
        public Parameter<double> B2mob30L { get; } = new Parameter<double>();
        public Parameter<double> B2mob30W { get; } = new Parameter<double>();
        public Parameter<double> B2mob3B0 { get; } = new Parameter<double>();
        public Parameter<double> B2mob3BL { get; } = new Parameter<double>();
        public Parameter<double> B2mob3BW { get; } = new Parameter<double>();
        public Parameter<double> B2mob3G0 { get; } = new Parameter<double>();
        public Parameter<double> B2mob3GL { get; } = new Parameter<double>();
        public Parameter<double> B2mob3GW { get; } = new Parameter<double>();
        public Parameter<double> B2mob400 { get; } = new Parameter<double>();
        public Parameter<double> B2mob40L { get; } = new Parameter<double>();
        public Parameter<double> B2mob40W { get; } = new Parameter<double>();
        public Parameter<double> B2mob4B0 { get; } = new Parameter<double>();
        public Parameter<double> B2mob4BL { get; } = new Parameter<double>();
        public Parameter<double> B2mob4BW { get; } = new Parameter<double>();
        public Parameter<double> B2mob4G0 { get; } = new Parameter<double>();
        public Parameter<double> B2mob4GL { get; } = new Parameter<double>();
        public Parameter<double> B2mob4GW { get; } = new Parameter<double>();
        public Parameter<double> B2ua00 { get; } = new Parameter<double>(0.2);
        public Parameter<double> B2ua0L { get; } = new Parameter<double>();
        public Parameter<double> B2ua0W { get; } = new Parameter<double>();
        public Parameter<double> B2uaB0 { get; } = new Parameter<double>();
        public Parameter<double> B2uaBL { get; } = new Parameter<double>();
        public Parameter<double> B2uaBW { get; } = new Parameter<double>();
        public Parameter<double> B2ub00 { get; } = new Parameter<double>();
        public Parameter<double> B2ub0L { get; } = new Parameter<double>();
        public Parameter<double> B2ub0W { get; } = new Parameter<double>();
        public Parameter<double> B2ubB0 { get; } = new Parameter<double>();
        public Parameter<double> B2ubBL { get; } = new Parameter<double>();
        public Parameter<double> B2ubBW { get; } = new Parameter<double>();
        public Parameter<double> B2u100 { get; } = new Parameter<double>(0.1);
        public Parameter<double> B2u10L { get; } = new Parameter<double>();
        public Parameter<double> B2u10W { get; } = new Parameter<double>();
        public Parameter<double> B2u1B0 { get; } = new Parameter<double>();
        public Parameter<double> B2u1BL { get; } = new Parameter<double>();
        public Parameter<double> B2u1BW { get; } = new Parameter<double>();
        public Parameter<double> B2u1D0 { get; } = new Parameter<double>();
        public Parameter<double> B2u1DL { get; } = new Parameter<double>();
        public Parameter<double> B2u1DW { get; } = new Parameter<double>();
        public Parameter<double> B2n00 { get; } = new Parameter<double>(1.4);
        public Parameter<double> B2n0L { get; } = new Parameter<double>();
        public Parameter<double> B2n0W { get; } = new Parameter<double>();
        public Parameter<double> B2nB0 { get; } = new Parameter<double>(0.5);
        public Parameter<double> B2nBL { get; } = new Parameter<double>();
        public Parameter<double> B2nBW { get; } = new Parameter<double>();
        public Parameter<double> B2nD0 { get; } = new Parameter<double>();
        public Parameter<double> B2nDL { get; } = new Parameter<double>();
        public Parameter<double> B2nDW { get; } = new Parameter<double>();
        public Parameter<double> B2vof00 { get; } = new Parameter<double>(1.8);
        public Parameter<double> B2vof0L { get; } = new Parameter<double>();
        public Parameter<double> B2vof0W { get; } = new Parameter<double>();
        public Parameter<double> B2vofB0 { get; } = new Parameter<double>();
        public Parameter<double> B2vofBL { get; } = new Parameter<double>();
        public Parameter<double> B2vofBW { get; } = new Parameter<double>();
        public Parameter<double> B2vofD0 { get; } = new Parameter<double>();
        public Parameter<double> B2vofDL { get; } = new Parameter<double>();
        public Parameter<double> B2vofDW { get; } = new Parameter<double>();
        public Parameter<double> B2ai00 { get; } = new Parameter<double>();
        public Parameter<double> B2ai0L { get; } = new Parameter<double>();
        public Parameter<double> B2ai0W { get; } = new Parameter<double>();
        public Parameter<double> B2aiB0 { get; } = new Parameter<double>();
        public Parameter<double> B2aiBL { get; } = new Parameter<double>();
        public Parameter<double> B2aiBW { get; } = new Parameter<double>();
        public Parameter<double> B2bi00 { get; } = new Parameter<double>();
        public Parameter<double> B2bi0L { get; } = new Parameter<double>();
        public Parameter<double> B2bi0W { get; } = new Parameter<double>();
        public Parameter<double> B2biB0 { get; } = new Parameter<double>();
        public Parameter<double> B2biBL { get; } = new Parameter<double>();
        public Parameter<double> B2biBW { get; } = new Parameter<double>();
        public Parameter<double> B2vghigh0 { get; } = new Parameter<double>(0.2);
        public Parameter<double> B2vghighL { get; } = new Parameter<double>();
        public Parameter<double> B2vghighW { get; } = new Parameter<double>();
        public Parameter<double> B2vglow0 { get; } = new Parameter<double>(-0.15);
        public Parameter<double> B2vglowL { get; } = new Parameter<double>();
        public Parameter<double> B2vglowW { get; } = new Parameter<double>();
        public Parameter<double> B2tox { get; } = new Parameter<double>(0.03);
        public Parameter<double> B2temp { get; } = new Parameter<double>(27.0); // NOTE: This is stored in celsius apparently
        public Parameter<double> B2vdd { get; } = new Parameter<double>(5.0);
        public Parameter<double> B2vgg { get; } = new Parameter<double>(5.0);
        public Parameter<double> B2vbb { get; } = new Parameter<double>(5.0);
        public Parameter<double> B2gateSourceOverlapCap { get; } = new Parameter<double>();
        public Parameter<double> B2gateDrainOverlapCap { get; } = new Parameter<double>();
        public Parameter<double> B2gateBulkOverlapCap { get; } = new Parameter<double>();
        public Parameter<double> B2channelChargePartitionFlag { get; } = new Parameter<double>();
        public Parameter<double> B2sheetResistance { get; } = new Parameter<double>();
        public Parameter<double> B2jctSatCurDensity { get; } = new Parameter<double>();
        public Parameter<double> B2bulkJctPotential { get; } = new Parameter<double>();
        public Parameter<double> B2bulkJctBotGradingCoeff { get; } = new Parameter<double>();
        public Parameter<double> B2sidewallJctPotential { get; } = new Parameter<double>();
        public Parameter<double> B2bulkJctSideGradingCoeff { get; } = new Parameter<double>();
        public Parameter<double> B2unitAreaJctCap { get; } = new Parameter<double>();
        public Parameter<double> B2unitLengthSidewallJctCap { get; } = new Parameter<double>();
        public Parameter<double> B2defaultWidth { get; } = new Parameter<double>(10.0);
        public Parameter<double> B2deltaLength { get; } = new Parameter<double>();
        public int B2type { get; private set; }
        #endregion

        #region Calculated constants
        public int pad { get; private set; }
        public double B2Cox { get; private set; }                         /* unit: F/cm**2 */
        public double B2vdd2 { get; private set; }
        public double B2vgg2 { get; private set; }
        public double B2vbb2 { get; private set; }
        public double B2Vtm { get; private set; }
        #endregion

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="name"></param>
        public BSIM2Model(string name) : base(name) { }

        /// <summary>
        /// Set parameter
        /// </summary>
        protected override void Param(int id, object value, Circuit ckt = null)
        {
            switch ((_c)id)
            {
                case _c.BSIM2_MOD_VFB0:
                    B2vfb0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VFBL:
                    B2vfbL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VFBW:
                    B2vfbW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_PHI0:
                    B2phi0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_PHIL:
                    B2phiL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_PHIW:
                    B2phiW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_K10:
                    B2k10.Par((double)value);
                    break;
                case _c.BSIM2_MOD_K1L:
                    B2k1L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_K1W:
                    B2k1W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_K20:
                    B2k20.Par((double)value);
                    break;
                case _c.BSIM2_MOD_K2L:
                    B2k2L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_K2W:
                    B2k2W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_ETA00:
                    B2eta00.Par((double)value);
                    break;
                case _c.BSIM2_MOD_ETA0L:
                    B2eta0L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_ETA0W:
                    B2eta0W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_ETAB0:
                    B2etaB0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_ETABL:
                    B2etaBL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_ETABW:
                    B2etaBW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_DELTAL:
                    B2deltaL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_DELTAW:
                    B2deltaW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB00:
                    B2mob00.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB0B0:
                    B2mob0B0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB0BL:
                    B2mob0BL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB0BW:
                    B2mob0BW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOBS00:
                    B2mobs00.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOBS0L:
                    B2mobs0L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOBS0W:
                    B2mobs0W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOBSB0:
                    B2mobsB0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOBSBL:
                    B2mobsBL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOBSBW:
                    B2mobsBW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB200:
                    B2mob200.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB20L:
                    B2mob20L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB20W:
                    B2mob20W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB2B0:
                    B2mob2B0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB2BL:
                    B2mob2BL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB2BW:
                    B2mob2BW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB2G0:
                    B2mob2G0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB2GL:
                    B2mob2GL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB2GW:
                    B2mob2GW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB300:
                    B2mob300.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB30L:
                    B2mob30L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB30W:
                    B2mob30W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB3B0:
                    B2mob3B0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB3BL:
                    B2mob3BL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB3BW:
                    B2mob3BW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB3G0:
                    B2mob3G0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB3GL:
                    B2mob3GL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB3GW:
                    B2mob3GW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB400:
                    B2mob400.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB40L:
                    B2mob40L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB40W:
                    B2mob40W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB4B0:
                    B2mob4B0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB4BL:
                    B2mob4BL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB4BW:
                    B2mob4BW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB4G0:
                    B2mob4G0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB4GL:
                    B2mob4GL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MOB4GW:
                    B2mob4GW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_UA00:
                    B2ua00.Par((double)value);
                    break;
                case _c.BSIM2_MOD_UA0L:
                    B2ua0L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_UA0W:
                    B2ua0W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_UAB0:
                    B2uaB0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_UABL:
                    B2uaBL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_UABW:
                    B2uaBW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_UB00:
                    B2ub00.Par((double)value);
                    break;
                case _c.BSIM2_MOD_UB0L:
                    B2ub0L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_UB0W:
                    B2ub0W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_UBB0:
                    B2ubB0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_UBBL:
                    B2ubBL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_UBBW:
                    B2ubBW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_U100:
                    B2u100.Par((double)value);
                    break;
                case _c.BSIM2_MOD_U10L:
                    B2u10L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_U10W:
                    B2u10W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_U1B0:
                    B2u1B0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_U1BL:
                    B2u1BL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_U1BW:
                    B2u1BW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_U1D0:
                    B2u1D0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_U1DL:
                    B2u1DL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_U1DW:
                    B2u1DW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_N00:
                    B2n00.Par((double)value);
                    break;
                case _c.BSIM2_MOD_N0L:
                    B2n0L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_N0W:
                    B2n0W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_NB0:
                    B2nB0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_NBL:
                    B2nBL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_NBW:
                    B2nBW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_ND0:
                    B2nD0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_NDL:
                    B2nDL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_NDW:
                    B2nDW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VOF00:
                    B2vof00.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VOF0L:
                    B2vof0L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VOF0W:
                    B2vof0W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VOFB0:
                    B2vofB0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VOFBL:
                    B2vofBL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VOFBW:
                    B2vofBW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VOFD0:
                    B2vofD0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VOFDL:
                    B2vofDL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VOFDW:
                    B2vofDW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_AI00:
                    B2ai00.Par((double)value);
                    break;
                case _c.BSIM2_MOD_AI0L:
                    B2ai0L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_AI0W:
                    B2ai0W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_AIB0:
                    B2aiB0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_AIBL:
                    B2aiBL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_AIBW:
                    B2aiBW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_BI00:
                    B2bi00.Par((double)value);
                    break;
                case _c.BSIM2_MOD_BI0L:
                    B2bi0L.Par((double)value);
                    break;
                case _c.BSIM2_MOD_BI0W:
                    B2bi0W.Par((double)value);
                    break;
                case _c.BSIM2_MOD_BIB0:
                    B2biB0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_BIBL:
                    B2biBL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_BIBW:
                    B2biBW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VGHIGH0:
                    B2vghigh0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VGHIGHL:
                    B2vghighL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VGHIGHW:
                    B2vghighW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VGLOW0:
                    B2vglow0.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VGLOWL:
                    B2vglowL.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VGLOWW:
                    B2vglowW.Par((double)value);
                    break;
                case _c.BSIM2_MOD_TOX:
                    B2tox.Par((double)value);
                    break;
                case _c.BSIM2_MOD_TEMP:
                    B2temp.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VDD:
                    B2vdd.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VGG:
                    B2vgg.Par((double)value);
                    break;
                case _c.BSIM2_MOD_VBB:
                    B2vbb.Par((double)value);
                    break;
                case _c.BSIM2_MOD_CGSO:
                    B2gateSourceOverlapCap.Par((double)value);
                    break;
                case _c.BSIM2_MOD_CGDO:
                    B2gateDrainOverlapCap.Par((double)value);
                    break;
                case _c.BSIM2_MOD_CGBO:
                    B2gateBulkOverlapCap.Par((double)value);
                    break;
                case _c.BSIM2_MOD_XPART:
                    B2channelChargePartitionFlag.Par((int)value);
                    break;
                case _c.BSIM2_MOD_RSH:
                    B2sheetResistance.Par((double)value);
                    break;
                case _c.BSIM2_MOD_JS:
                    B2jctSatCurDensity.Par((double)value);
                    break;
                case _c.BSIM2_MOD_PB:
                    B2bulkJctPotential.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MJ:
                    B2bulkJctBotGradingCoeff.Par((double)value);
                    break;
                case _c.BSIM2_MOD_PBSW:
                    B2sidewallJctPotential.Par((double)value);
                    break;
                case _c.BSIM2_MOD_MJSW:
                    B2bulkJctSideGradingCoeff.Par((double)value);
                    break;
                case _c.BSIM2_MOD_CJ:
                    B2unitAreaJctCap.Par((double)value);
                    break;
                case _c.BSIM2_MOD_CJSW:
                    B2unitLengthSidewallJctCap.Par((double)value);
                    break;
                case _c.BSIM2_MOD_DEFWIDTH:
                    B2defaultWidth.Par((double)value);
                    break;
                case _c.BSIM2_MOD_DELLENGTH:
                    B2deltaLength.Par((double)value);
                    break;
                case _c.BSIM2_MOD_NMOS:
                        B2type = 1;
                    break;
                case _c.BSIM2_MOD_PMOS:
                        B2type = -1;
                    break;
                default:
                    throw new BadParameterException();
            }
        }

        /// <summary>
        /// Ask parameter
        /// </summary>
        protected override object Ask(int id, Circuit ckt = null)
        {
            switch ((_c)id)
            {
                case _c.BSIM2_MOD_VFB0:
                    return B2vfb0.Value;
                case _c.BSIM2_MOD_VFBL:
                    return B2vfbL.Value;
                case _c.BSIM2_MOD_VFBW:
                    return B2vfbW.Value;
                case _c.BSIM2_MOD_PHI0:
                    return B2phi0.Value;
                case _c.BSIM2_MOD_PHIL:
                    return B2phiL.Value;
                case _c.BSIM2_MOD_PHIW:
                    return B2phiW.Value;
                case _c.BSIM2_MOD_K10:
                    return B2k10.Value;
                case _c.BSIM2_MOD_K1L:
                    return B2k1L.Value;
                case _c.BSIM2_MOD_K1W:
                    return B2k1W.Value;
                case _c.BSIM2_MOD_K20:
                    return B2k20.Value;
                case _c.BSIM2_MOD_K2L:
                    return B2k2L.Value;
                case _c.BSIM2_MOD_K2W:
                    return B2k2W.Value;
                case _c.BSIM2_MOD_ETA00:
                    return B2eta00.Value;
                case _c.BSIM2_MOD_ETA0L:
                    return B2eta0L.Value;
                case _c.BSIM2_MOD_ETA0W:
                    return B2eta0W.Value;
                case _c.BSIM2_MOD_ETAB0:
                    return B2etaB0.Value;
                case _c.BSIM2_MOD_ETABL:
                    return B2etaBL.Value;
                case _c.BSIM2_MOD_ETABW:
                    return B2etaBW.Value;
                case _c.BSIM2_MOD_DELTAL:
                    return B2deltaL; // Doesn't make sense... = value->rValue;
                case _c.BSIM2_MOD_DELTAW:
                    return B2deltaW; // Doesn't make sense... = value->rValue;
                case _c.BSIM2_MOD_MOB00:
                    return B2mob00.Value;
                case _c.BSIM2_MOD_MOB0B0:
                    return B2mob0B0.Value;
                case _c.BSIM2_MOD_MOB0BL:
                    return B2mob0BL.Value;
                case _c.BSIM2_MOD_MOB0BW:
                    return B2mob0BW.Value;
                case _c.BSIM2_MOD_MOBS00:
                    return B2mobs00.Value;
                case _c.BSIM2_MOD_MOBS0L:
                    return B2mobs0L.Value;
                case _c.BSIM2_MOD_MOBS0W:
                    return B2mobs0W.Value;
                case _c.BSIM2_MOD_MOBSB0:
                    return B2mobsB0.Value;
                case _c.BSIM2_MOD_MOBSBL:
                    return B2mobsBL.Value;
                case _c.BSIM2_MOD_MOBSBW:
                    return B2mobsBW.Value;
                case _c.BSIM2_MOD_MOB200:
                    return B2mob200.Value;
                case _c.BSIM2_MOD_MOB20L:
                    return B2mob20L.Value;
                case _c.BSIM2_MOD_MOB20W:
                    return B2mob20W.Value;
                case _c.BSIM2_MOD_MOB2B0:
                    return B2mob2B0.Value;
                case _c.BSIM2_MOD_MOB2BL:
                    return B2mob2BL.Value;
                case _c.BSIM2_MOD_MOB2BW:
                    return B2mob2BW.Value;
                case _c.BSIM2_MOD_MOB2G0:
                    return B2mob2G0.Value;
                case _c.BSIM2_MOD_MOB2GL:
                    return B2mob2GL.Value;
                case _c.BSIM2_MOD_MOB2GW:
                    return B2mob2GW.Value;
                case _c.BSIM2_MOD_MOB300:
                    return B2mob300.Value;
                case _c.BSIM2_MOD_MOB30L:
                    return B2mob30L.Value;
                case _c.BSIM2_MOD_MOB30W:
                    return B2mob30W.Value;
                case _c.BSIM2_MOD_MOB3B0:
                    return B2mob3B0.Value;
                case _c.BSIM2_MOD_MOB3BL:
                    return B2mob3BL.Value;
                case _c.BSIM2_MOD_MOB3BW:
                    return B2mob3BW.Value;
                case _c.BSIM2_MOD_MOB3G0:
                    return B2mob3G0.Value;
                case _c.BSIM2_MOD_MOB3GL:
                    return B2mob3GL.Value;
                case _c.BSIM2_MOD_MOB3GW:
                    return B2mob3GW.Value;
                case _c.BSIM2_MOD_MOB400:
                    return B2mob400.Value;
                case _c.BSIM2_MOD_MOB40L:
                    return B2mob40L.Value;
                case _c.BSIM2_MOD_MOB40W:
                    return B2mob40W.Value;
                case _c.BSIM2_MOD_MOB4B0:
                    return B2mob4B0.Value;
                case _c.BSIM2_MOD_MOB4BL:
                    return B2mob4BL.Value;
                case _c.BSIM2_MOD_MOB4BW:
                    return B2mob4BW.Value;
                case _c.BSIM2_MOD_MOB4G0:
                    return B2mob4G0.Value;
                case _c.BSIM2_MOD_MOB4GL:
                    return B2mob4GL.Value;
                case _c.BSIM2_MOD_MOB4GW:
                    return B2mob4GW.Value;
                case _c.BSIM2_MOD_UA00:
                    return B2ua00.Value;
                case _c.BSIM2_MOD_UA0L:
                    return B2ua0L.Value;
                case _c.BSIM2_MOD_UA0W:
                    return B2ua0W.Value;
                case _c.BSIM2_MOD_UAB0:
                    return B2uaB0.Value;
                case _c.BSIM2_MOD_UABL:
                    return B2uaBL.Value;
                case _c.BSIM2_MOD_UABW:
                    return B2uaBW.Value;
                case _c.BSIM2_MOD_UB00:
                    return B2ub00.Value;
                case _c.BSIM2_MOD_UB0L:
                    return B2ub0L.Value;
                case _c.BSIM2_MOD_UB0W:
                    return B2ub0W.Value;
                case _c.BSIM2_MOD_UBB0:
                    return B2ubB0.Value;
                case _c.BSIM2_MOD_UBBL:
                    return B2ubBL.Value;
                case _c.BSIM2_MOD_UBBW:
                    return B2ubBW.Value;
                case _c.BSIM2_MOD_U100:
                    return B2u100.Value;
                case _c.BSIM2_MOD_U10L:
                    return B2u10L.Value;
                case _c.BSIM2_MOD_U10W:
                    return B2u10W.Value;
                case _c.BSIM2_MOD_U1B0:
                    return B2u1B0.Value;
                case _c.BSIM2_MOD_U1BL:
                    return B2u1BL.Value;
                case _c.BSIM2_MOD_U1BW:
                    return B2u1BW.Value;
                case _c.BSIM2_MOD_U1D0:
                    return B2u1D0.Value;
                case _c.BSIM2_MOD_U1DL:
                    return B2u1DL.Value;
                case _c.BSIM2_MOD_U1DW:
                    return B2u1DW.Value;
                case _c.BSIM2_MOD_N00:
                    return B2n00.Value;
                case _c.BSIM2_MOD_N0L:
                    return B2n0L.Value;
                case _c.BSIM2_MOD_N0W:
                    return B2n0W.Value;
                case _c.BSIM2_MOD_NB0:
                    return B2nB0.Value;
                case _c.BSIM2_MOD_NBL:
                    return B2nBL.Value;
                case _c.BSIM2_MOD_NBW:
                    return B2nBW.Value;
                case _c.BSIM2_MOD_ND0:
                    return B2nD0.Value;
                case _c.BSIM2_MOD_NDL:
                    return B2nDL.Value;
                case _c.BSIM2_MOD_NDW:
                    return B2nDW.Value;
                case _c.BSIM2_MOD_VOF00:
                    return B2vof00.Value;
                case _c.BSIM2_MOD_VOF0L:
                    return B2vof0L.Value;
                case _c.BSIM2_MOD_VOF0W:
                    return B2vof0W.Value;
                case _c.BSIM2_MOD_VOFB0:
                    return B2vofB0.Value;
                case _c.BSIM2_MOD_VOFBL:
                    return B2vofBL.Value;
                case _c.BSIM2_MOD_VOFBW:
                    return B2vofBW.Value;
                case _c.BSIM2_MOD_VOFD0:
                    return B2vofD0.Value;
                case _c.BSIM2_MOD_VOFDL:
                    return B2vofDL.Value;
                case _c.BSIM2_MOD_VOFDW:
                    return B2vofDW.Value;
                case _c.BSIM2_MOD_AI00:
                    return B2ai00.Value;
                case _c.BSIM2_MOD_AI0L:
                    return B2ai0L.Value;
                case _c.BSIM2_MOD_AI0W:
                    return B2ai0W.Value;
                case _c.BSIM2_MOD_AIB0:
                    return B2aiB0.Value;
                case _c.BSIM2_MOD_AIBL:
                    return B2aiBL.Value;
                case _c.BSIM2_MOD_AIBW:
                    return B2aiBW.Value;
                case _c.BSIM2_MOD_BI00:
                    return B2bi00.Value;
                case _c.BSIM2_MOD_BI0L:
                    return B2bi0L.Value;
                case _c.BSIM2_MOD_BI0W:
                    return B2bi0W.Value;
                case _c.BSIM2_MOD_BIB0:
                    return B2biB0.Value;
                case _c.BSIM2_MOD_BIBL:
                    return B2biBL.Value;
                case _c.BSIM2_MOD_BIBW:
                    return B2biBW.Value;
                case _c.BSIM2_MOD_VGHIGH0:
                    return B2vghigh0.Value;
                case _c.BSIM2_MOD_VGHIGHL:
                    return B2vghighL.Value;
                case _c.BSIM2_MOD_VGHIGHW:
                    return B2vghighW.Value;
                case _c.BSIM2_MOD_VGLOW0:
                    return B2vglow0.Value;
                case _c.BSIM2_MOD_VGLOWL:
                    return B2vglowL.Value;
                case _c.BSIM2_MOD_VGLOWW:
                    return B2vglowW.Value;
                case _c.BSIM2_MOD_TOX:
                    return B2tox.Value;
                case _c.BSIM2_MOD_TEMP:
                    return B2temp.Value;
                case _c.BSIM2_MOD_VDD:
                    return B2vdd.Value;
                case _c.BSIM2_MOD_VGG:
                    return B2vgg.Value;
                case _c.BSIM2_MOD_VBB:
                    return B2vbb.Value;
                case _c.BSIM2_MOD_CGSO:
                    return B2gateSourceOverlapCap.Value;
                case _c.BSIM2_MOD_CGDO:
                    return B2gateDrainOverlapCap.Value;
                case _c.BSIM2_MOD_CGBO:
                    return B2gateBulkOverlapCap.Value;
                case _c.BSIM2_MOD_XPART:
                    return B2channelChargePartitionFlag.Value;
                case _c.BSIM2_MOD_RSH:
                    return B2sheetResistance.Value;
                case _c.BSIM2_MOD_JS:
                    return B2jctSatCurDensity.Value;
                case _c.BSIM2_MOD_PB:
                    return B2bulkJctPotential.Value;
                case _c.BSIM2_MOD_MJ:
                    return B2bulkJctBotGradingCoeff.Value;
                case _c.BSIM2_MOD_PBSW:
                    return B2sidewallJctPotential.Value;
                case _c.BSIM2_MOD_MJSW:
                    return B2bulkJctSideGradingCoeff.Value;
                case _c.BSIM2_MOD_CJ:
                    return B2unitAreaJctCap.Value;
                case _c.BSIM2_MOD_CJSW:
                    return B2unitLengthSidewallJctCap.Value;
                case _c.BSIM2_MOD_DEFWIDTH:
                    return B2defaultWidth.Value;
                case _c.BSIM2_MOD_DELLENGTH:
                    return B2deltaLength.Value;
                default:
                    throw new BadParameterException();
            }
        }

        /// <summary>
        /// Setup the model
        /// </summary>
        /// <param name="ckt"></param>
        public override void Temperature(Circuit ckt)
        {
            /* Default value Processing for B2 MOSFET Models */
            /* Some Limiting for Model Parameters */
            if (B2bulkJctPotential < 0.1)
            {
                B2bulkJctPotential.Value = 0.1;
            }
            if (B2sidewallJctPotential < 0.1)
            {
                B2sidewallJctPotential.Value = 0.1;
            }

            B2Cox = 3.453e-13 / (B2tox * 1.0e-4); /* in F/cm**2 */
            B2vdd2 = 2.0 * B2vdd;
            B2vgg2 = 2.0 * B2vgg;
            B2vbb2 = 2.0 * B2vbb;
            B2Vtm = 8.625e-5 * (B2temp + 273.0);

            base.Temperature(ckt);
        }
    }
}
